﻿using CommunityToolkit.Mvvm.Input;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using MaterialDesignThemes.Wpf;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using UpperComputer.WPF.Entry.Common.Extensions;
using UpperComputer.WPF.Entry.Models;
using YFurion.Application;
using YFurion.Localization;
using YFurion.Session;

namespace UpperComputer.WPF.Entry.Common
{
    public class BaseViewModel : BaseDto, ITransient
    {
        /// <summary>
        /// 取消令牌命令
        /// </summary>
        public IRelayCommand<object> CancelTokenCommand { get; }

        /// <summary>
        /// 加载命令
        /// </summary>
        public IAsyncRelayCommand<object> LoadCommand { get; }

        /// <summary>
        /// 消息提示栏
        /// </summary>
        public Snackbar Snackbar { get; set; } = MainWindow.Snackbar;

        /// <summary>
        /// 会话对象
        /// </summary>
        protected IYSession YSession { get; } = Furion.App.GetService<IYSession>();

        /// <summary>
        /// 分布式缓存对象
        /// </summary>
        protected IDistributedCache DistributedCache { get; } = Furion.App.GetService<IDistributedCache>();

        /// <summary>
        /// 语言模型对象数组
        /// </summary>
        public NameValueModel<string>[] CultureModels { get; } = new NameValueModel<string>[]
        {
            new NameValueModel<string>("中文简体",Constant.LANG_ZH_CN),
            new NameValueModel<string>("English",Constant.LANG_EN_US)
        };

        protected ILocalizationManager Lang { get; } = Furion.App.GetService<ILocalizationManager>();
        /// <summary>
        /// 语言
        /// </summary>
        public string Culture
        {
            get => Lang.Culture;
            set => SetProperty(Lang.Culture, value, Lang, (lang, n) => lang.Culture = n);
        }

        private string _error;
        /// <summary>
        /// 错误提示
        /// </summary>
        public new string Error
        {
            get => _error;
            set => SetProperty(ref _error, Lang[value]);
        }

        public BaseViewModel()
        {
            CancelTokenCommand = new RelayCommand<object>(CancelTokenCommand_Exetue);
            LoadCommand = new AsyncRelayCommand<object>(LoadCommand_Exetue, LoadCommand_CanExetue);
        }

        private void CancelTokenCommand_Exetue(object parameter)
        {
            CancelToken(parameter);
        }

        protected virtual void CancelToken(object parameter)
        {
            LoadCommand.CancelToken();
        }

        private bool LoadCommand_CanExetue(object parameter)
        {
            return CanLoad(parameter);
        }

        /// <summary>
        /// 是否可以加载虚方法
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        protected virtual bool CanLoad(object parameter)
        {
            return !LoadCommand.IsRunning;
        }

        private Task LoadCommand_Exetue(object parameter, CancellationToken cancellationToken)
        {
            return LoadAsync(parameter, cancellationToken);
        }

        /// <summary>
        /// 异步加载虚方法
        /// </summary>
        /// <param name="parameter"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected virtual Task LoadAsync(object parameter, CancellationToken cancellationToken)
        {
            return Task.CompletedTask;
        }

        /// <summary>
        /// 设置语言
        /// </summary>
        protected void SetLang()
        {
            List<ResourceDictionary> dictionaryList = new List<ResourceDictionary>();
            foreach (ResourceDictionary dictionary in System.Windows.Application.Current.Resources.MergedDictionaries)
            {
                dictionaryList.Add(dictionary);
            }
            string requestedCulture = $"pack://application:,,,/UpperComputer.WPF.Entry;component/Resources/I18N/{Culture}.xaml";
            ResourceDictionary resourceDictionary = dictionaryList.FirstOrDefault(d => d.Source != null && d.Source.OriginalString.Equals(requestedCulture));
            if (resourceDictionary != null)
            {
                System.Windows.Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary);
                System.Windows.Application.Current.Resources.MergedDictionaries.Add(resourceDictionary);
            }
            CultureInfo culture = new CultureInfo(Culture);
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
        }

        protected async Task<object> ShowRootDialog(object content)
        {
            MainWindow.Snackbar.MessageQueue.Clear();
            return await DialogHost.Show(content,Constant.DIALOG_IDENTIFIER_ROOT);
        }

        /// <summary>
        /// 关闭根对话框
        /// </summary>
        /// <param name="parameter"></param>
        protected void CloseRootDialog(object parameter = null)
        {
            DialogHost.Close(Constant.DIALOG_IDENTIFIER_ROOT, parameter);
        }

        /// <summary>
        /// 异步尝试执行命令
        /// </summary>
        /// <param name="func">委托</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns></returns>
        protected async Task TryExecuteCommandAysnc(Func<CancellationToken, Task> func, CancellationToken cancellationToken)
        {
            try
            {
                await func(cancellationToken);
            }
            catch (AppFriendlyException ex)
            {
                Error = ex.Message;
            }
        }

        /// <summary>
        /// 异步尝试执行命令(有参数)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func">委托</param>
        /// <param name="parameter">参数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns></returns>
        protected async Task TryExecuteCommandAysnc<T>(Func<T, CancellationToken, Task> func, T parameter, CancellationToken cancellationToken)
        {
            try
            {
                await func(parameter, cancellationToken);
            }
            catch (AppFriendlyException ex)
            {
                Error = ex.Message;
            }
        }
    }
}